package org.ws.task.zookeeper.node;

import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.ws.task.model.NodeMetadata;
import org.ws.task.model.NodeStatus;
import org.ws.task.zookeeper.listener.NodeListenerManager;

public abstract class AbstractNode {

    private static Logger log = LoggerFactory.getLogger(AbstractNode.class.getName());

    protected final String id;
    protected final CuratorFramework curatorClient;
    protected final NodeListenerManager nodeListenerManager;
    protected final String namespace;

    public AbstractNode(String id, String namespace, CuratorFramework curatorClient, NodeListenerManager nodeListenerManager) {
        this.id = id;
        this.namespace = namespace;
        this.curatorClient = curatorClient;
        this.nodeListenerManager = nodeListenerManager;
    }

    protected void updateNodeData(String path, NodeMetadata node, CreateMode createMode) throws Exception {
        log.debug("updateNodeData:{} -> {}",path,node);
        if(node.getPort()<=0){
            node.setStatus(NodeStatus.RECOVERING);
        }
        byte[] data = NodeDataCodec.encode(node);
        Stat stat = this.curatorClient.checkExists().forPath(path);
        if(stat == null){
            this.curatorClient.create()
                    .creatingParentsIfNeeded()
                    .withMode(createMode)
                    .forPath(path, data);
        }
        else {
            stat = new Stat();
            this.curatorClient.getData().storingStatIn(stat).forPath(path);
            try {
                this.curatorClient.setData().withVersion(stat.getVersion()).forPath(path, data);
            } catch (KeeperException.BadVersionException e) {
                // 重试一次
                this.curatorClient.getData().storingStatIn(stat).forPath(path);
                this.curatorClient.setData().withVersion(stat.getVersion()).forPath(path, data);
            }
        }
    }
}
